package mylab.base.foundation.lang;

import java.util.function.Consumer;

import cn.hutool.log.StaticLog;

/**
 * 回调接口，通知成功、失败、异常
 *
 */
public interface Callback<T> {

    /**
     * 执行成功时
     *
     * @param result 成功时的返回值
     */
    void onSuccess(T result);

    /**
     * 执行失败时
     *
     * @param cause 失败原因
     */
    default void onFailure(String cause){
        StaticLog.warn(cause);
    }

    /**
     * 执行时发生异常
     *
     * @param throwable 异常
     */
    default void onException(Throwable throwable){
        StaticLog.error(throwable);
    }


    static <T> Callback<T> simple(Consumer<T> consumer) {
        return new SuccessCallback<>(consumer);
    }

    static <T> Callback<T> simple(Callback<T> callback, Consumer<T> consumer) {
        return new SuccessCallback<>(callback, consumer);
    }


    static void dealOnSuccess(Callback<Void> callback) {
        if (callback != null) {
            callback.onSuccess(null);
        }
    }

    static <T> void dealOnSuccess(Callback<T> callback, T result) {
        if (callback != null) {
            callback.onSuccess(result);
        }
    }

    static void dealOnFailure(Callback<?> callback, String cause) {
        if (callback != null) {
            callback.onFailure(cause);
        }
    }

    static void dealOnException(Callback<?> callback, Throwable throwable) {
        if (callback != null) {
            callback.onException(throwable);
        }
    }


    class SuccessCallback<T> implements Callback<T> {
        Callback<T> callback;
        Consumer<T> consumer;

        public SuccessCallback(Consumer<T> consumer) {
            this.consumer = consumer;
        }

        public SuccessCallback(Callback<T> callback, Consumer<T> consumer) {
            this.callback = callback;
            this.consumer = consumer;
        }

        @Override
        public void onSuccess(T result) {
            consumer.accept(result);

            if (callback != null) {
                callback.onSuccess(result);
            }
        }

        @Override
        public void onFailure(String cause) {
            if (callback != null) {
                callback.onFailure(cause);
            }
        }

        @Override
        public void onException(Throwable throwable) {
            if (callback != null) {
                callback.onException(throwable);
            }
        }
    }
}